#!/usr/bin/python
#coding:utf-8
#codeby     道长且阻
#email      ydhcui@suliu.net
#website    http://www.suliu.net

import gevent
from gevent import socket
from gevent.server import StreamServer
from multiprocessing import cpu_count

class Request(object):
    def __init__(self,request):
        self.request    = request
        self.host       = None
        self.port       = 80
        self.method     = 'GET'
        self.uri        = '/'
        self.lenth      = len(self.request)
        self.protocol   = 'HTTP/1.1'
        self.headers    = {}
        self.content    = None
        try:self.parse()
        except:pass

    def parse(self):
        head,self.content = self.request.split('\r\n\r\n')
        lines = head.split('\r\n')
        '''解析请求方法和uri'''
        self.method,self.uri,self.protocol = lines[0].split()
        self.method = self.method.upper()

        '''解析其他header'''
        for line in lines[1:]:
            head = line.split(':')
            self.headers[head[0]] = ':'.join(head[1:]).strip()

        '''处理目标主机和端口'''
        host_port = self.headers['Host'].split(':')
        self.host = host_port[0]
        if len(host_port)==2:
            self.port = int(host_port[1])

class Tunnel(object):
    BUFFER = 8192
    def __init__(self,client,addr):
        self.client = client
        self.addr   = addr
        ishead = True
        data = b''
        while True:
            buff = self.client.recv(self.BUFFER)
            print(self.addr,len(buff))
            data += buff
            if not buff:break
            if '\r\n\r\n' in buff:
                print(len(buff),'head')
                req = Request(buff)
        req.request = data
        print(data)
        if req.method in ['CONNECT']:
            print(req.method)
            self.httpstunnl(req)
        else:
            print(req.method)
            #print(req)
            self.httptunnl(req)
        self.client.close()

    def httptunnl(self,req):
        sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
        #sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.connect((req.host,req.port))
        sock.send(req.request)
        while True:
            buff = sock.recv(self.BUFFER)
            self.client.send(buff)
            if not buff:break
        sock.close()

    def httpstunnl(self,req):
        sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
        #sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        sock.connect((req.host,req.port))
        gevent.joinall([
            gevent.spawn(self.dotunnl,self.client,sock,False),
            gevent.spawn(self.dotunnl,sock,self.client,True),
        ])

    def dotunnl(self,recver,sender,rd=False):
        while True:
            buff = recver.recv(self.BUFFER)
            sender.send(buff)
            if not buf:break
        if rd:
            recver.close()
            sender.close()

def Proxy(h='0.0.0.0',p=8080):
    p=StreamServer((h,p),Tunnel)
    p.start()
    print('start processes: ok')
    p.serve_forever()



c = Proxy()
c.start()

